package com.peng.jackson;

import static com.fasterxml.jackson.databind.node.JsonNodeType.STRING;

import java.util.Iterator;
import java.util.Map;

import org.apache.commons.lang3.tuple.Pair;
import org.junit.jupiter.api.Test;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeType;
import com.fasterxml.jackson.databind.node.ObjectNode;

import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * JacksonTreeSample
 *
 * @author lupeng
 * Created on 2022-04-16
 */
public class JacksonTreeSample {

    static ObjectMapper objectMapper = new ObjectMapper();

    static {
        //json中可以写注释
        objectMapper.enable(JsonParser.Feature.ALLOW_COMMENTS);
        //重复检测
        objectMapper.enable(JsonParser.Feature.STRICT_DUPLICATE_DETECTION);
        //关闭属性匹配失败报错，宽松的转换策略
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    }

    @Test
    public void s1() throws JsonProcessingException {
        String json = """
                {
                  "arr": [
                    {
                      "name": "jack",
                      "age": 11,
                      "factor": 0.66
                    },
                    {
                      "name": "guoguo",
                      "age": 2,
                      "factor": 0.99
                    }
                  ],
                  "size": 1234567890,
                  "data": "{\\"extra\\":{\\"firstName\\":\\"zhang\\",\\"lastName\\":\\"san\\"}, \\"arr1\\":[1,2,3]}"
                }
                """.strip();


        JsonNode jsonNode = objectMapper.readTree(json);
        recursiveParser(jsonNode);

        System.out.println(objectMapper.writeValueAsString(jsonNode));
    }

    private void recursiveParser(JsonNode node) {
        // 获取jackson的Node节点类型
        JsonNodeType nodeType = node.getNodeType();
        System.out.println(nodeType);
        switch (nodeType) {
            case OBJECT -> {
                ObjectNode objNode = (ObjectNode) node;
                Iterator<Map.Entry<String, JsonNode>> iterator = objNode.fields();
                while (iterator.hasNext()) {
                    Map.Entry<String, JsonNode> entry = iterator.next();
                    JsonNode value = entry.getValue();
                    Pair<Boolean, JsonNode> result = tryDecodeJsonNode(value);
                    if (result.getLeft()) {
                        JsonNode decodeJsonNode = result.getRight();
                        objNode.put(entry.getKey(), decodeJsonNode);
                        value = decodeJsonNode;
                    }
                    recursiveParser(value);
                }
            }
            case ARRAY -> {
                ArrayNode arrayNode = (ArrayNode) node;
                for (int i = 0; i < arrayNode.size(); i++) {
                    JsonNode value = arrayNode.get(i);
                    Pair<Boolean, JsonNode> result = tryDecodeJsonNode(value);
                    if (result.getLeft()) {
                        JsonNode decodeJsonNode = result.getRight();
                        arrayNode.insert(i, decodeJsonNode);
                        value = decodeJsonNode;
                    }
                    recursiveParser(value);
                }
            }
        }
    }

    private Pair<Boolean, JsonNode> tryDecodeJsonNode(JsonNode jsonNode) {
        if (jsonNode.getNodeType() != STRING) {
            return Pair.of(false, null);
        }
        try {
            JsonNode node = objectMapper.readTree(jsonNode.asText());
            return Pair.of(true, node);
        } catch (JsonProcessingException e) {
            return Pair.of(false, null);
        }
    }


    @NoArgsConstructor
    @Data
    static class Bean1 {

        @JsonProperty("name")
        private String name;
        @JsonProperty("age")
        private Integer age;
        //@JsonProperty("factor")
        //private Double factor;
    }

    @Test
    public void s2() throws JsonProcessingException {
        String json = """
                {
                  "name": "guoguo",
                  "age": 2,
                  "factor": 0.99
                }
                """.strip();
        ObjectMapper om = new ObjectMapper();
        //开启宽松的json解析，java类的字段和json不完全匹配也能转换成功
        om.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        Bean1 bean1 = om.readValue(json, Bean1.class);
        System.out.println(bean1);
    }
}
